import React, {FC, useCallback, useEffect, useMemo, useRef, useState} from "react";
import useStateRef from "../../customUse/useStateRef.tsx";
import {AxiosGet} from "../../services/HttpService.tsx";
import {getObjByRule, isArray, isString} from "../../utils";
import useDebounce from "../../customUse/useDebounce.tsx";
import {Checkbox, Input, List} from "antd";
import InfiniteScroll from "react-infinite-scroll-component";
import "./css/MultiSelectText.less";


interface MultiSelectTextProps {
    value?: any,
    labelKey?: string,
    valueKey?: string,
    joinKey?: string,
    ds?: any,
    params: any,
    url: string,
    format?: any,
    options?: any[],
    disabled: boolean,
    showSearch?: boolean,
    isBlockNode?: boolean
    isAddSearchValue?: boolean
    onChange: Function,
}

const MultiSelectText: FC<MultiSelectTextProps> = (props) => {

    const selectOptionRef = useRef();
    const allSelectOptionRef = useRef<any[]>();

    const [selectOption, setSelectOption] = useStateRef([], selectOptionRef),
        [value, setValue] = useState<any>(undefined);

    const loadOption = useCallback(async () => {
        let {format = {id: "id", value: "value", label: "zhCn|usEn|ptBr"}, params = {}}: {
            format?: any,
            params: any
        } = props;
        let options: any[] = [];
        if (props.url) {
            const {data = []}: { data: any[] } = await AxiosGet(props.url, params);
            options = data.map(node => {
                return isString(node) ? {id: node, value: node, label: node} : getObjByRule(node, {
                    id: "id",
                    value: "value",
                    label: "zhCn|usEn|ptBr",
                    ...format
                }, true);
            })
        } else if (props.options) {
            options = props.options || [];
        }
        setSelectOption(options);
        allSelectOptionRef.current = options;
    }, [props.options, props.url, props.params]);

    useEffect(() => {
        loadOption();
    }, [props.params, props.url, props.options]);

    useEffect(() => {
        if (value !== props.value) {
            setValue(props.value)
        }
    }, [props.value]);

    useEffect(() => {
        const {ds = {}}: { ds?: any } = props;
        let newValue = ds.value || props.value;
        if (newValue) {
            const {joinKey = ","}: { joinKey?: string } = props;
            setValue(isString(newValue) ? newValue.split(joinKey) : newValue);
        }
    }, [props.ds]);

    const handleChangeCheck: Function = useCallback((checkedValue: any = []) => {
        const {joinKey}: { joinKey?: string } = props;
        setValue(checkedValue);
        props.onChange && props.onChange(isArray(checkedValue) && joinKey ? checkedValue.join(joinKey) : checkedValue);
    }, [props.onChange, props.joinKey]);

    const handleSearch: Function = useDebounce((text: string) => {
        const {labelKey = "label", valueKey = "value", isAddSearchValue = false}: {
            labelKey?: string,
            valueKey?: string,
            isAddSearchValue?: boolean
        } = props;
        let newSelectOption: any[] = allSelectOptionRef.current.filter((item: any) => {
            return item[labelKey].indexOf(text) !== -1 || item[valueKey].indexOf(text) !== -1
        });
        if (isAddSearchValue && !newSelectOption.length) {
            let node: object = {
                [labelKey]: text,
                [valueKey]: text
            }
            newSelectOption.push(node);
        }
        setSelectOption(JSON.parse(JSON.stringify(newSelectOption)));
    }, 500, [selectOption, props.labelKey, props.valueKey, props.isAddSearchValue]);

    const renderMultiItem = useCallback((row: any) => {
        const {labelKey = "label", valueKey = "value"}: { labelKey?: string, valueKey?: string } = props;
        return (
            <List.Item className="sf_core_multi_select_text_infinite_list_item">
                <Checkbox value={row[valueKey]}>
                    <span className="col-text-a-line-show">{row[labelKey]}</span>
                </Checkbox>
            </List.Item>
        )
    }, [props.labelKey, props.valueKey]);

    const renderMultiSelectText = useMemo(() => {
        if (!selectOptionRef.current) {
            return null
        }
        const {valueKey = "value", showSearch = true, disabled = false, isBlockNode = false}:
            {
                valueKey?: string,
                showSearch?: boolean,
                disabled?: boolean,
                isBlockNode?: boolean
            } = props;
        return (
            <div className="sf_core_multi_select_text">
                {showSearch ? <Input.Search
                    size="small"
                    className="sf_core_multi_select_text_search"
                    onSearch={handleSearch}/> : null}
                <Checkbox.Group
                    className="sf_core_multi_select_text_checkbox"
                    value={value}
                    disabled={disabled}
                    onChange={handleChangeCheck}
                >
                    <InfiniteScroll
                        className="sf_core_multi_select_text_infinite"
                        // height={100}
                        dataLength={selectOption.length}
                        hasMore={false}
                    >
                        <List
                            className={"sf_core_multi_select_text_infinite_list " + (isBlockNode ? "sf_core_multi_select_text_block" : "")}
                            rowKey={valueKey}
                            dataSource={selectOption}
                            renderItem={renderMultiItem}
                        />
                    </InfiniteScroll>
                </Checkbox.Group>
            </div>
        )
    }, [props, selectOption, value])

    return (renderMultiSelectText);
};

export default React.memo(MultiSelectText);